/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



package com.android1.amarena2d.nodes.ui;

import com.android1.amarena2d.input.TouchListener;
import com.android1.amarena2d.nodes.EntityContainer;
import com.android1.amarena2d.nodes.sprites.BaseSprite;
import com.android1.amarena2d.texture.TextureFrame;
import com.badlogic.gdx.audio.Sound;

public class Button extends EntityContainer<BaseSprite> {

    public static final class State {
        public static final int Disabled = 0;
        public static final int Active = 1;
        public static final int Pressed = 2;
        //For ToggleButton
        public static final int Selected = 3;
    }

    protected TextureFrame disabledFrame;
    protected TextureFrame activeFrame;
    protected TextureFrame pressedFrame;

    protected int state = State.Active;

    protected Sound tapSound;

    protected ButtonListenerAdapter buttonListenerAdapter;

    public Button(BaseSprite entity) {
        super(entity);
        activeFrame = entity.getTextureFrame();
        initListener();
    }

    protected void initListener() {
        this.buttonListenerAdapter = new ButtonListenerAdapter(this);
    }

    public void setActive() {
        this.state = State.Active;
    }

    public TextureFrame getDisabledFrame() {
        return disabledFrame;
    }

    public Button setDisabledFrame(TextureFrame disabledFrame) {
        this.disabledFrame = disabledFrame;
        return this;
    }

    public TextureFrame getActiveFrame() {
        return activeFrame;
    }

    public Button setActiveFrame(TextureFrame activeFrame) {
        this.activeFrame = activeFrame;
        return this;
    }

    public TextureFrame getPressedFrame() {
        return pressedFrame;
    }

    public Button setPressedFrame(TextureFrame pressedFrame) {
        this.pressedFrame = pressedFrame;
        return this;
    }

    public String getStateString() {
        if (this.state == State.Active)
            return "Active";
        else if (this.state == State.Disabled)
            return "Disabled";
        else if (this.state == State.Pressed)
            return "Pressed";
        else if (this.state == State.Selected)
            return "Selected";

        return null;
    }

    public int getState() {
        return state;
    }

    public boolean isStateActive() {
        return state == State.Active;
    }

    public boolean isStatePressed() {
        return state == State.Pressed;
    }

    public boolean isStateInactive() {
        return state == State.Disabled;
    }

    public void setStateActive() {
        this.setState(State.Active);
        entity.setTextureFrame(activeFrame);

    }

    public void setStatePressed() {
        this.setState(State.Pressed);
        if (pressedFrame == null)
            entity.setTextureFrame(activeFrame);
        else
            entity.setTextureFrame(pressedFrame);
    }

    protected void setState(int state) {
        if (state == State.Active || state == State.Disabled || state == State.Pressed || state == State.Selected) {
            this.state = state;
            if (this.buttonListenerAdapter.getButtonListener() != null)
                this.buttonListenerAdapter.getButtonListener().onStateChange(this, state);
        }
    }


    public void setStateDisabled() {
        this.setState(State.Disabled);
        if (disabledFrame == null)
            entity.setTextureFrame(activeFrame);
        else
            entity.setTextureFrame(disabledFrame);
    }

    public Sound getTapSound() {
        return tapSound;
    }

    public void setTapSound(Sound tapSound) {
        this.tapSound = tapSound;
    }

    @Override
    public void init() {
        super.init();
        entity.touch().makeTouchable(buttonListenerAdapter).setNotifyNoHit(true);
    }

    public Button setListener(Listener listener) {
        this.buttonListenerAdapter.setButtonListener(listener);
        return this;
    }


    protected static class ButtonListenerAdapter implements TouchListener {

        Button button;
        Listener buttonListener;
        boolean hit;

        public ButtonListenerAdapter(Button button) {
            this.button = button;
        }

        public Listener getButtonListener() {
            return buttonListener;
        }

        public void setButtonListener(Listener buttonListener) {
            this.buttonListener = buttonListener;
        }

        public boolean onTouchDown(float x, float y, int pointer, boolean isHit) {
            if (!isHit)
                return false;
            if (buttonListener != null)
                buttonListener.onTapDown(button, x, y, pointer);
            if (button.isStateActive()) {
                button.setStatePressed();
            }
            if (button.tapSound != null)
                button.tapSound.play();
            hit = true;
            return isHit;
        }

        @Override
        public boolean onTouchUp(float x, float y, int pointer, boolean isHit) {
            if (buttonListener != null) {
                buttonListener.onTapUp(button, x, y, pointer);
                if (hit && isHit) {
                    buttonListener.onTap(button, x, y, pointer);

                }
            }
            if (button.isStateActive() || button.isStatePressed())
                button.setStateActive();
            hit = false;
            return isHit;
        }

        @Override
        public boolean onTouchDragged(float x, float y, int pointer, boolean isHit) {
            return false;
        }
    }

    public static class Listener {

        public void onTapDown(Button button, float x, float y, int pointer) {

        }

        public void onTapUp(Button button, float x, float y, int pointer) {

        }

        public void onTap(Button button, float x, float y, int pointer) {

        }

        public void onStateChange(Button button, int state) {

        }
    }


}
